﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Win104.IEC104
{
    public class Apdu
    {
        private int SendSeqNum = 0;
        private int ReceiveSeqNum = 0;
        private ApciType apciType;
        private Asdu asdu = null;

        public Apdu() { }

        public Apdu(ByteBody data)
        {
            int start = data.GetByte() & 0xff;
            int len = data.GetByte() & 0xff;
            Console.WriteLine("启动帧：" + start.ToString("X2"));
            Console.WriteLine("APDU长度：" + len);

            //控制域
            byte[] controlFields = new byte[4];
            if (start != 104)
                throw new Exception("启动帧错误");
            else if (len < 4 || len > 253)
                throw new Exception("帧长度有误");
            else
            {
                controlFields = data.GetBytes(4);
                if((controlFields[0]&0x01) == 0)
                {
                    //I帧
                    this.apciType = ApciType.I_FORMAT;
                    //发送序列号
                    SendSeqNum = ((controlFields[0] & 0xfe) >> 1) + ((controlFields[1] & 0xff) << 7);

                    //接收序列号
                    ReceiveSeqNum = ((controlFields[2] & 0xfe) >> 1) + ((controlFields[3] & 0xff) << 7);
                    Console.WriteLine("I帧，发送序列号：" + SendSeqNum + "，接收序列号：" + ReceiveSeqNum);
                }
                else if ((controlFields[0] & 0x03) == 1)
                {
                    //S帧
                    this.apciType = ApciType.S_FORMAT;
                    ReceiveSeqNum = ((controlFields[2] & 0xfe) >> 1) + ((controlFields[3] & 0xff) << 7);
                    Console.WriteLine("S帧，接收序列号：" + ReceiveSeqNum);
                }
                else if ((controlFields[0] & 0x03) == 3)
                {
                    //U帧
                    if(controlFields[0] == 0x07)
                    {
                        this.apciType = ApciType.U_START_ACT;
                        Console.WriteLine("U帧，启动命令");
                    }
                    else if(controlFields[0] == 0x0B)
                    {
                        this.apciType = ApciType.U_START_CON;
                        Console.WriteLine("U帧，启动命令");
                    }
                    else if (controlFields[0] == 0x13)
                    {
                        this.apciType = ApciType.U_STOP_ACT;
                        Console.WriteLine("U帧，停止命令");
                    }
                    else if (controlFields[0] == 0x23)
                    {
                        this.apciType = ApciType.U_STOP_CON;
                        Console.WriteLine("U帧，停止确认");
                    }
                    else if (controlFields[0] == 0x43)
                    {
                        this.apciType = ApciType.U_TEST_ACT;
                        Console.WriteLine("U帧，测试命令");
                    }
                    else if (controlFields[0] == 0x83)
                    {
                        this.apciType = ApciType.U_TEST_CON;
                        Console.WriteLine("U帧，测试确认");
                    }
                }
            }
            if (len > 6)
                this.asdu = new Asdu(data);
        }

        public ApciType GetApciType()
        {
            return apciType;
        }

        public int GetSendSeqNumber()
        {
            return SendSeqNum;
        }

        public int GetReceiveSeqNumber()
        {
            return ReceiveSeqNum;
        }

        public Asdu GetAsdu()
        {
            return asdu;
        }


    }

    public enum ApciType
    {
        /// <summary>
        /// I帧
        /// </summary>
        I_FORMAT = 1,
        /// <summary>
        /// S帧
        /// </summary>
        S_FORMAT = 2,
        /// <summary>
        /// U帧，测试确认
        /// </summary>
        U_TEST_CON= 3,
        /// <summary>
        /// U帧，测试命令
        /// </summary>
        U_TEST_ACT = 4,
        /// <summary>
        /// U帧，启动确认
        /// </summary>
        U_START_CON = 5,
        /// <summary>
        /// U帧，启动命令
        /// </summary>
        U_START_ACT = 6,
        /// <summary>
        /// U帧，停止确认
        /// </summary>
        U_STOP_CON = 7,
        /// <summary>
        /// U帧，停止命令
        /// </summary>
        U_STOP_ACT = 8
    }
}
